package com.haozi.ehub.core.handler;

import com.haozi.ehub.core.enums.ExceptionEnum;
import com.haozi.ehub.core.util.CodeUtils;
import com.haozi.ehub.core.util.JWTUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;

/**
 * 自定义token鉴权过滤器,用bean形式使用
 * @author ：terry
 * @date ：Created in 2020/7/6 17:09
 * @version: 1.0
 */
@SuppressWarnings(value = "all")
public class SecurityTokenAuthenticationFilter extends OncePerRequestFilter {
    
    @Autowired
    private UserDetailsService userDetailsService;
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        //获取请求头中的token
        String authHeader = request.getHeader(CodeUtils.TOKEN_HEADER);
        final String tokenPrefix = CodeUtils.TOKEN_PREFIX;

        //验证token是不是空和token的格式是否正确
        if (authHeader != null && authHeader.startsWith(tokenPrefix)) {
            //获取最终的token
            final String authToken = authHeader.substring(tokenPrefix.length());

            //如果需要加密token则将此行代码解除注释
            //authToken = RSAEncoderUtils.decrypt(authToken);

            //检查token
            if(JWTUtils.checkJWT(authToken) == null){
                throw new RuntimeException(ExceptionEnum.TOKEN_ERROR.getEnmsg());
            }

            //从token中获取用户信息
            //User user = JWTUtils.getUser(authToken);

            List<GrantedAuthority> authByEcrypt = JWTUtils.getAuthByEcrypt(authToken);
            //从token中获取用户名称,该名称格式为A_username,在通过加形成
            String username = JWTUtils.getUsername(authToken);
            if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
                //不知道为什么验证JWT要去数据库再查一次,如果执行了则会再一次比对用户名和密码是否存在
                //可能是想再验证用户的正确性,再通过查询出的用户进行鉴权
                //User user = (User) userDetailsService.loadUserByUsername(username);

                //该方法最终会执行UserDetailsService的loadUserByUsername方法,
                //然而并没有，这说法是百度上的大佬教我的，哼╭(╯^╰)╮
                UsernamePasswordAuthenticationToken authentication =
                        new UsernamePasswordAuthenticationToken(null, null, authByEcrypt);
                authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));

                //听说这个使用生命周期仅为一次请求( ╯▽╰)
                SecurityContextHolder.getContext().setAuthentication(authentication);
            }else{
                throw new RuntimeException(ExceptionEnum.TOKEN_ERROR.getEnmsg());
            }
        }
        //通过请求
        filterChain.doFilter(request, response);
    }
}
